import { Injectable } from "@nestjs/common"
import { ProgramEntity } from "./program.entity"
import { InjectRepository } from "@nestjs/typeorm"
import { ILike, IsNull, Not, Repository } from "typeorm"
import { getCurrentDate } from "../../utils/getCurrentDate"
import { AuthorizationEntity } from "../authorization/authorization.entity"
import { PiracyEntity } from "../piracy/piracy.entity"

@Injectable()
export class ProgramService {
  constructor(
    @InjectRepository(ProgramEntity)
    private readonly programEntity: Repository<ProgramEntity>,
    @InjectRepository(AuthorizationEntity)
    private readonly authorizationEntity: Repository<AuthorizationEntity>,
    @InjectRepository(PiracyEntity)
    private readonly piracyEntity: Repository<PiracyEntity>
  ) {}

  /**
   * Add application
   * @param body
   * @param res
   */
  async add(body: any, res: any): Promise<void> {
    try {
      // 1.Set self increasing id
      const { maxId } = await this.programEntity
        .createQueryBuilder("program")
        .withDeleted()
        .select("MAX(program.id)", "maxId")
        .getRawOne()
      const id = maxId === null ? 2001110500 : parseInt(maxId) + 1
      // 2.Determine if it is duplicated
      const result = await this.programEntity.find({
        where: {
          name: body.name
        }
      })
      if (result.length !== 0) {
        res.json({ status: "error", message: "添加失败，应用名重复！" })
        return
      }
      // 3.Execute add
      await this.programEntity.save({
        id,
        create_date: getCurrentDate(),
        ...body
      })
      res.json({ status: "success", message: "应用添加成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Obtain application name lists
   * @param res
   */
  async getNameLists(res: any): Promise<void> {
    try {
      const data = await this.programEntity.find({ select: ["id", "name"] })
      res.json(data)
    } catch (err) {
      console.log(err)
    }
  }

  /**
   * Obtain all application information
   * @param res
   */
  async getAll(res: any): Promise<void> {
    try {
      const data = await this.programEntity.find()
      res.json(data)
    } catch (err) {
      console.log(err)
    }
  }

  /**
   * Obtain all application information with soft deletion
   * @param res
   */
  async getAllWidthDeleted(res: any): Promise<void> {
    try {
      const data = await this.programEntity.find({
        withDeleted: true,
        where: {
          deleteAt: Not(IsNull())
        }
      })
      res.json(data)
    } catch (err) {
      console.log(err)
    }
  }

  /**
   * Update application status
   * @param body
   * @param res
   */
  async updateStatus(body: any, res: any): Promise<void> {
    try {
      const { id, status } = body
      await this.programEntity.update(parseInt(id), {
        status: parseInt(status)
      })
      res.json({ status: "success", message: "应用状态修改成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Search application information
   * @param body
   * @param res
   */
  async search(body: any, res: any): Promise<void> {
    try {
      const result = await this.programEntity.find({
        where: {
          name: ILike(`%${body.name}%`)
        }
      })
      res.json(result)
    } catch (err) {
      console.log(err)
    }
  }

  /**
   * Search application information with soft deletion
   * @param body
   * @param res
   */
  async searchWidthDeleted(body: any, res: any): Promise<void> {
    try {
      const result = await this.programEntity.find({
        withDeleted: true,
        where: {
          name: ILike(`%${body.name}%`),
          deleteAt: Not(IsNull())
        }
      })
      res.json(result)
    } catch (err) {
      console.log(err)
    }
  }

  /**
   * Update application information
   * @param body
   * @param res
   * @description Update application information and synchronously modify the application name of authorization management information and piracy record information
   */
  async update(body: any, res: any): Promise<void> {
    try {
      const { id, data, name } = body // name is initial application name，data.name is updated application name
      // Determine if it is duplicated
      const isRepeat = await this.programEntity.find({
        where: {
          name: data.name
        }
      })
      if (isRepeat.length > 0 && data.name !== name) {
        res.json({ status: "error", message: "信息修改失败，应用名重复！" })
        return
      }
      // Execute update
      await this.programEntity.update(id, data)
      // Synchronously update authorization information
      await this.authorizationEntity.update(
        { app_id: id },
        { app_name: data.name }
      )
      // Synchronously update piracy information
      await this.piracyEntity.update({ app_id: id }, { app_name: data.name })
      res.json({ status: "success", message: "应用信息修改成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Soft deletion application information
   * @param body
   * @param res
   */
  async delete(body: any, res: any): Promise<void> {
    const { id } = body
    try {
      await this.programEntity.softDelete(id)
      res.json({ status: "success", message: "应用信息删除成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Real deletion application information
   * @param body
   * @param res
   */
  async remove(body: any, res: any): Promise<void> {
    const { id } = body
    try {
      await this.programEntity.delete(id)
      res.json({ status: "success", message: "应用信息删除成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Restore application information
   * @param body
   * @param res
   */
  async restore(body: any, res: any): Promise<void> {
    try {
      const { id, name } = body
      const isRepeat = await this.programEntity.find({
        where: {
          name
        }
      })
      if (isRepeat.length !== 0) {
        res.json({ status: "error", message: "恢复失败，应用名重复！" })
        return
      }
      await this.programEntity.update(id, { deleteAt: null })
      res.json({ status: "success", message: "应用信息恢复成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Batch soft deletion application information
   * @param body
   * @param res
   */
  async deleteGroup(body: any, res: any): Promise<void> {
    const { ids } = body
    try {
      for (let i = 0; i < ids.length; i++) {
        await this.programEntity.softDelete(ids[i])
      }
      res.json({ status: "success", message: "应用信息删除成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Batch real deletion application information
   * @param body
   * @param res
   */
  async removeGroup(body: any, res: any): Promise<void> {
    const { ids } = body
    try {
      for (let i = 0; i < ids.length; i++) {
        await this.programEntity.delete(ids[i])
      }
      res.json({ status: "success", message: "应用信息删除成功！" })
    } catch (err) {
      console.log(err)
      res.json({ status: "error", message: "服务器内部错误，请稍后再试！" })
    }
  }

  /**
   * Obtain application number
   * @param res
   */
  async count(res: any): Promise<void> {
    try {
      const data = await this.programEntity.count()
      res.json(data)
    } catch (err) {
      console.log(err)
    }
  }
}
